//#ifndef EIGEN_USE_MKL_ALL
//#define EIGEN_USE_MKL_ALL
//#endif

#include <Eigen/Dense>
#include <iostream>
#include "../data_collector/data_collector.hpp"
#include <cmath>
#include <set>
#include <ctime>

using namespace std;

//apply pca to d.
void PCA(MatrixXd& d, double percentage)
{
	MatrixXd X = d.block(0, 0, d.rows() - 1, d.cols());
	RowVectorXd labels = d.block(d.rows() - 1, 0, 1, d.cols());
	VectorXd m = X.rowwise().mean();
	MatrixXd X_u = X.colwise() - m;

	MatrixXd covX = X_u*X_u.transpose(); //calc COV matrix
	SelfAdjointEigenSolver<MatrixXd> sv(covX);
	if (sv.info() != Success)
		abort();
	VectorXd evalue = sv.eigenvalues(); //get eigenvalues
	MatrixXd evector = sv.eigenvectors(); // get eigenvectors

	//sort eigenvalues DESC
	VectorXi index = VectorXi::LinSpaced(X.rows(), 0, X.rows() - 1);
	std::sort(index.data(), index.data() + index.size(),
		[evalue](int l, int r) {return evalue(l) > evalue(r); });

	//choose top _d
	int _d = std::floor(X.rows()*percentage);
	MatrixXd W(evector.cols(),_d);
	for (int i = 0; i < _d; i++)
		W.col(i) = evector.col(index(i)); //generate W with _d eigenvectors according to top N eigenvalues

	d.resize(_d + 1, d.cols());
	d<<(W.transpose()*X).eval(),labels;
}

int main()
{
	DataCollector d;
	d.readDataFromFile("iris.data");
	MatrixXd X = *d.DataList();
	PCA(X, 0.5);
	cout << X << endl;
	return 0;
}